package cn.buk.tms.eotms.dao;

import cn.buk.common.util.DateUtil;
import cn.buk.tms.common.constant.TmsOrderConstant;
import cn.buk.tms.eotms.dao.factory.OperationLogFactory;
import cn.buk.tms.eotms.entity.*;
import cn.buk.tms.eotms.sc.SearchCarOrderCriteria;
import org.springframework.stereotype.Component;

import jakarta.persistence.criteria.*;
import jakarta.transaction.Transactional;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import static cn.buk.tms.common.constant.TmsOrderConstant.*;

@Component
@Transactional
public class CarOrderDaoImpl extends AbstractDao implements CarOrderDao {

  @Override
  public int createCarOrder(RentalCarOrder o) {
    em.persist(o);

    OperationLog log = OperationLogFactory.createCarOrderLog();
    log.setEnterpriseId(o.getEnterpriseId());
    log.setOrderId(o.getId());
    log.setOperator(o.getOperator());
    log.setContent("创建订单");

    em.persist(log);

    return o.getId();
  }

  @Override
  public int submitRentalCarOrder(int ownerId, int userId, String orderNo, int vehicleTypeId, String vehicleTypeName, int supplierVehicleTypeId, double price, double discount, String linkPhone, String linkman, String email, int payType, String remark, int flightOrderId) {
    List<RentalCarOrder> orders = em.createQuery("select o from RentalCarOrder o where o.enterpriseId = :ownerId and o.orderNo = :orderNo", RentalCarOrder.class)
            .setParameter("ownerId", ownerId)
            .setParameter("orderNo", orderNo)
            .getResultList();
    if (orders.size() != 1) {
      throw new RuntimeException("Cannot find the order(" + orderNo + ").");
    }

    RentalCarOrder orderInfo = orders.get(0);
    if (orderInfo.getStatus() != RENTAL_CAR_ORDER_STATUS_NOT_SUBMITTED) {
      throw new RuntimeException("The order(" + orderNo + ") is not not-submitted.");
    }

    //提交订单，等待审批
    orderInfo.setStatus(TmsOrderConstant.RENTAL_CAR_ORDER_STATUS_SUBMITTED);
    orderInfo.setVehicleTypeId(vehicleTypeId);
    orderInfo.setVehicleTypeName(vehicleTypeName);
    orderInfo.setSupplierVehicleTypeId(supplierVehicleTypeId);
    orderInfo.setPrice(price);
    orderInfo.setDiscount(discount);
    orderInfo.setMobile(linkPhone);
    orderInfo.setName(linkman);
    orderInfo.setEmail(email);
    orderInfo.setPayType(payType);
    orderInfo.setRemark(remark);
    orderInfo.setCreateDate(DateUtil.getCurDate());
    orderInfo.setLastUpdate(DateUtil.getCurDateTime());
    if (flightOrderId > 0) {
      orderInfo.setFlightOrderId(flightOrderId);
    }

    em.merge(orderInfo);

    User user = em.find(User.class, userId);
    OperationLog log = OperationLogFactory.createCarOrderLog();
    log.setEnterpriseId(ownerId);
    log.setOrderId(orderInfo.getId());
    log.setOperator(user.getUsername());
    String memo = "提交订单(价格：" + price + ").";
    log.setContent(memo);

    em.persist(log);

    return orderInfo.getId();
  }

  @Override
  public List<RentalCarOrder> searchOrders(final int ownerId, final int customerId, SearchCarOrderCriteria sc) {
    List<RentalCarOrder> results = null;

    CriteriaBuilder cb = em.getCriteriaBuilder();
    CriteriaQuery<RentalCarOrder> cq = cb.createQuery(RentalCarOrder.class);
    Root<RentalCarOrder> root = cq.from(RentalCarOrder.class);
    root.alias("o");


    var predicates0 = getPredicates_searchOrders(ownerId, customerId, sc, cb, root);

    //计算根据条件查询得出的数据总数
    CriteriaQuery<Long> countQuery = cb.createQuery(Long.class);
    Root<RentalCarOrder> countRoot = countQuery.from(RentalCarOrder.class);
    countRoot.alias("o");

    var predicates1 = getPredicates_searchOrders(ownerId, customerId, sc, cb, countRoot);

    // count items
    countQuery.select(cb.count(countRoot)).where(predicates1.toArray(new Predicate[predicates1.size()]));
    Long count = em.createQuery(countQuery).getSingleResult();

    //查询
    cq.select(root).where(predicates0.toArray(new Predicate[predicates0.size()]));

    List<jakarta.persistence.criteria.Order> orderByes = new ArrayList<>();
    orderByes.add(cb.desc(root.get("id")));

    cq.orderBy(orderByes);

    int maxResults = count.intValue();
    if (maxResults > 0) {
      sc.getPage().setRowCount(maxResults);

      results = em.createQuery(cq)
              .setFirstResult(sc.getPage().getFirstPosition())
              .setMaxResults(sc.getPage().getPageSize())
              .getResultList();

    }

    if (results == null) {
      results = new ArrayList<>();
    }

    return results;

  }

  private List<Predicate> getPredicates_searchOrders(int ownerId, int customerId, SearchCarOrderCriteria sc, CriteriaBuilder cb, Root<RentalCarOrder> root) {
    List<Predicate> predicates = new ArrayList<>();

    Predicate predicate = cb.conjunction();
    predicates.add(predicate);

    predicate = cb.equal(root.get(RentalCarOrder_.enterpriseId), ownerId);
    predicates.add(predicate);

    predicate = cb.equal(root.get(RentalCarOrder_.customerId), customerId);
    predicates.add(predicate);

    if (sc.getOrderNo() != null && sc.getOrderNo().trim().length() > 0) {
      //订单号查找
      predicate = cb.equal(root.get(RentalCarOrder_.orderNo), sc.getOrderNo());
      predicates.add(predicate);
    } else {
      //非订单号查找
      if (sc.getStatus() > 0) {
        predicate = cb.equal(root.get(RentalCarOrder_.status), sc.getStatus());
        predicates.add(predicate);
      } else {
        //未提交的订单默认不显示
        predicate = cb.notEqual(root.get(RentalCarOrder_.status), RENTAL_CAR_ORDER_STATUS_NOT_SUBMITTED);
        predicates.add(predicate);

        predicate = cb.notEqual(root.get(RentalCarOrder_.status), RENTAL_CAR_ORDER_STATUS_CANCELED);
        predicates.add(predicate);
      }

//      if (sc.getSupplierOrderNo() != null && sc.getSupplierOrderNo().trim().length() > 0) {
//        predicate = cb.equal(root.get(RentalCarOrder_.supplierOrderId), sc.getSupplierOrderNo());
//        predicates.add(predicate);
//      }

      if (sc.getMobile().length() > 0) {
        predicate = cb.like(root.get(RentalCarOrder_.mobile), "%" + sc.getMobile() + "%");
        predicates.add(predicate);
      }

      if (sc.getDdate() != null) {
        //用车日期
        predicate = cb.greaterThan(root.get(RentalCarOrder_.useTime), sc.getDdate());

        final Date endDate = DateUtil.addDays(sc.getDdate(), 1);
        predicate = cb.and(predicate, cb.lessThan(root.get(RentalCarOrder_.useTime), endDate));

        predicates.add(predicate);
      }

      if (sc.getName().length() > 0) {
        //联系人
        predicate = cb.like(root.get(RentalCarOrder_.name), "%" + sc.getName() + "%");
        predicates.add(predicate);
      }


      if (sc.getOp1().length() > 0) {
        //查找指定用户名的订单
        predicate = cb.equal(root.get(RentalCarOrder_.operator), sc.getOp1());
        predicates.add(predicate);
      } if (sc.getDepartmentId() != null) {
        //只查找本部门的
        List<String> usernames = doGetCustomerDepartmentOperator(ownerId, customerId, sc.getDepartmentId());


        Path<String> path = root.get(RentalCarOrder_.operator);
        CriteriaBuilder.In<String> in = cb.in(path);
        for(String username: usernames) {
          in.value(username);
        }

        predicates.add(in);
      }

//      if (sc.getUsername().length() > 0) {
//        //采购用户名
//
//        Subquery<User> subQueryUser = cq.subquery(User.class);
//        Root<User> subRoot = subQueryUser.from(User.class);
//        subQueryUser.select(subRoot);
//        subQueryUser.alias("u");
//
//        List<Predicate> subQueryPredicates = new ArrayList<>();
//        subQueryPredicates
//                .add(cb.equal(root.get(RentalCarOrder_.enterpriseId), subRoot.get(User_.id)));
//
//        subQueryPredicates.add(
//                cb.like(subRoot.get(User_.username), "%" + sc.getUsername() + "%"));
//
//        subQueryUser.where(subQueryPredicates.toArray(new Predicate[]{}));
//
//        predicates.add(cb.exists(subQueryUser));
//      }
    }
    return predicates;
  }

  @Override
  public RentalCarOrder getOrderById(int orderId) {
    return em.find(RentalCarOrder.class, orderId);
  }

  @Override
  public int cancelRentalCarOrder(int ownerId, int customerId, String username, int orderId) {
    int retCode = em.createQuery("update RentalCarOrder o set o.status = :newStatus, o.lastUpdate = :lastUpdate "
            + "where o.id = :id and o.enterpriseId = :enterpriseId and o.customerId = :customerId and o.status = :oldStatus")
            .setParameter("newStatus", RENTAL_CAR_ORDER_STATUS_CANCELED)
            .setParameter("lastUpdate", DateUtil.getCurDateTime())
            .setParameter("id", orderId)
            .setParameter("enterpriseId", ownerId)
            .setParameter("customerId", customerId)
            .setParameter("oldStatus", TmsOrderConstant.RENTAL_CAR_ORDER_STATUS_WAITING)
            .executeUpdate();
    if (retCode != 1) {
      throw new RuntimeException("取消订单失败, 请检查订单状态");
    }

    OperationLog log = OperationLogFactory.createCarOrderLog();
    log.setEnterpriseId(ownerId);
    log.setOrderId(orderId);
    log.setOperator(username);

    String memo = "取消订单";
    log.setContent(memo);

    em.persist(log);

    return retCode;
  }

  @Override
  public int updateRentalCarOrderPaid(final int userId, final int orderId) {
    User user = em.find(User.class, userId);
    RentalCarOrder carOrder = em.find(RentalCarOrder.class, orderId);
    final int customerId = carOrder.getCustomer().getId();

    int retCode = em.createQuery("update RentalCarOrder o " +
            "set o.payStatus = :payStatus, " +
            "o.lastUpdate = :lastUpdate " +
            "where o.id = :id and (o.payStatus is null or o.payStatus <> :payStatus)")
            .setParameter("id", orderId)
            .setParameter("payStatus", 1)
            .setParameter("lastUpdate", DateUtil.getCurDateTime())
            .executeUpdate();
    if (retCode != 1) {
      throw new RuntimeException("update rental car order pay status failed.");
    }

    OperationLog log = OperationLog.createLog(carOrder.getEnterpriseId(), OPERATING_OBJECT_CAR_ORDER);
    log.setCustomerId(customerId);
    log.setOperator(user.getUsername());
    log.setOrderId(orderId);
    log.setContent("订单支付完成");
    em.persist(log);

    return retCode;
  }

  @Override
  public int approveRentalCarOrder(int ownerId, int customerId, String username, int orderId, int denyCode, String denyReason) {
    int retCode = 0;
    if (denyCode == 0) {
      //审批通过
      retCode = em
              .createQuery("update RentalCarOrder o set o.status = :newStatus, " +
                      "o.approvalInfo.approvalStatus = 1, " +
                      "o.lastUpdate = :lastUpdate " +
                      "where o.id = :id " +
                      "and o.enterpriseId = :enterpriseId " +
                      "and o.customer.id = :customerId " +
                      "and o.status = :oldStatus")
              .setParameter("id", orderId)
              .setParameter("enterpriseId", ownerId)
              .setParameter("customerId", customerId)
              .setParameter("oldStatus", TmsOrderConstant.RENTAL_CAR_ORDER_STATUS_SUBMITTED)
              .setParameter("newStatus", TmsOrderConstant.RENTAL_CAR_ORDER_STATUS_WAITING)
              .setParameter("lastUpdate", DateUtil.getCurDateTime())
              .executeUpdate();

      if (retCode == 1) {
        OperationLog log = createRentalCarOrderLog(ownerId, customerId, orderId, username, "审批通过");
        em.persist(log);
      }
    } else {
      //审批拒绝
      retCode = em
              .createQuery("update RentalCarOrder o set o.status = :newStatus, " +
                      "o.approvalInfo.approvalStatus = 0, " +
                      "o.approvalInfo.approvalDenyCode = :denyCode, " +
                      "o.approvalInfo.approvalDenyReason = :denyReason, " +
                      "o.lastUpdate = :lastUpdate " +
                      "where o.id = :id " +
                      "and o.enterpriseId = :enterpriseId " +
                      "and o.customer.id = :customerId " +
                      "and o.status = :oldStatus")
              .setParameter("id", orderId)
              .setParameter("enterpriseId", ownerId)
              .setParameter("customerId", customerId)
              .setParameter("oldStatus", TmsOrderConstant.RENTAL_CAR_ORDER_STATUS_SUBMITTED)
              .setParameter("newStatus", TmsOrderConstant.RENTAL_CAR_ORDER_STATUS_CANCELED)
              .setParameter("denyCode", denyCode + "")
              .setParameter("denyReason", denyReason)
              .setParameter("lastUpdate", DateUtil.getCurDateTime())
              .executeUpdate();

      if (retCode == 1) {
        OperationLog log = createRentalCarOrderLog(ownerId, customerId, orderId, username, "审批拒绝(" + denyReason + ")，订单取消");
        em.persist(log);
        retCode = 2;
      }
    }



    return retCode;
  }

  @Override
  public List<RentalCarOrder> searchByFlightOrderId(int ownerId, int flightOrderId) {
    return em.createQuery("select o from RentalCarOrder o " +
            "where o.enterpriseId = :enterpriseId " +
            "and o.flightOrderId = :flightOrderId " +
            "and o.status <> :status", RentalCarOrder.class)
            .setParameter("enterpriseId", ownerId)
            .setParameter("flightOrderId", flightOrderId)
            .setParameter("status", RENTAL_CAR_ORDER_STATUS_CANCELED)
            .getResultList();
  }

  private OperationLog createRentalCarOrderLog(int ownerId, int customerId, int orderId, String username, String remark) {
    OperationLog log = OperationLogFactory.createCarOrderLog();
    log.setEnterpriseId(ownerId);
    log.setCustomerId(customerId);
    log.setOperator(username);
    log.setOrderId(orderId);
    log.setContent(remark);
    return log;
  }
}
